package com.heima.comment.service.impl;

import com.heima.comment.service.CommentHotService;
import com.heima.comment.service.CommentService;
import com.heima.common.constants.cloud.tencent.TencentConstants;
import com.heima.common.exception.CustException;
import com.heima.feigns.UserFeign;
import com.heima.model.behavior.pojos.ApLikesBehavior;
import com.heima.model.comment.dtos.CommentDTO;
import com.heima.model.comment.dtos.CommentLikeDTO;
import com.heima.model.comment.dtos.CommentSaveDTO;
import com.heima.model.comment.pojos.ApComment;
import com.heima.model.comment.pojos.ApCommentLike;
import com.heima.model.comment.vos.ApCommentVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.threadlocal.AppThreadLocalUtils;
import com.heima.model.user.pojos.ApUser;
import com.heima.tencentcloud.scan.ContentSecurityScan;
import com.heima.utils.common.string.KeywordFilterUtil;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.tms.v20201229.models.TextModerationResponse;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author XHui
 * @Since 2024/3/4 15:50
 * @Version 1.0
 */
@Service
public class CommentServiceImpl implements CommentService {

    @Resource
    private MongoTemplate mongoTemplate;
    @Resource
    private ContentSecurityScan contentSecurityScan;
    @Resource
    private UserFeign userFeign;


    @Override
    public ResponseResult saveComment(CommentSaveDTO dto) {
        ApUser loggedUser = AppThreadLocalUtils.getUser();
        // 1. 使用腾讯云内容安全审核，检测评论是否合法
        try {
            TextModerationResponse textModerationResponse = contentSecurityScan.textScan(dto.getContent());
            // 2. 更新评论数
            String suggestion = textModerationResponse.getSuggestion();
            String content = dto.getContent();
            String[] keywords = textModerationResponse.getKeywords();
            switch (suggestion) {
                case TencentConstants.CONTENT_SUGGESTION_BLOCK:
                    // 更新评论数
                    // 更新评论状态为待审核
                    content = KeywordFilterUtil.filterKeywords(content, keywords);
                    break;
                case TencentConstants.CONTENT_SUGGESTION_REVIEW:
                    break;
                case TencentConstants.CONTENT_SUGGESTION_PASS:
                    break;
            }
            // 3. 根据userId调用feign查询用户信息
            ResponseResult<ApUser> responseResult = userFeign.findUserById(loggedUser.getId());
            buildApComment(dto, content, responseResult);
            return ResponseResult.okResult();
            // 3. 返回结果
        } catch (TencentCloudSDKException e) {
            throw new RuntimeException(e);
        }
    }

    private ApComment buildApComment(CommentSaveDTO dto, String content, ResponseResult<ApUser> responseResult) {
        ApComment apComment = new ApComment();
        apComment.setContent(content);
        apComment.setAuthorId(responseResult.getData().getId());
        apComment.setAuthorName(responseResult.getData().getName());
        apComment.setImage(responseResult.getData().getImage());
        apComment.setArticleId(dto.getArticleId());
        apComment.setCreatedTime(new Date());
        apComment.setLikes(0);
        apComment.setReply(0);
        apComment.setFlag(ApComment.Flag.NORMAL.getValue());
        apComment.setType(ApComment.Type.ARTICLE.getValue());
        ApComment commentDB = mongoTemplate.insert(apComment);
        return commentDB;
    }

    @Resource
    private CommentHotService commentHotService;

    @Resource(name = "likesRedissonClient")
    private RedissonClient redissonClient;

    @Override
    //@Transactional(rollbackFor = RuntimeException.class)
    public ResponseResult likeOperation(CommentLikeDTO dto) {
        // 1. 根据评论ID查询评论详情
        String commentId = dto.getCommentId();
        ApUser loggedUser = AppThreadLocalUtils.getUser();


        // 2. 分析用户的行为是 点赞 还是 取消点赞 评论
        Short isLike = dto.getOperation();
        Query query = new Query(Criteria.where("commentId")
                .is(commentId)
                .and("authorId")
                .is(loggedUser.getId())
        );

        RLock rLock = redissonClient.getLock("likes-lock");
        rLock.lock(); // 尝试获取锁资源，若已被其他线程抢到，则代码阻塞在此
        // 2.0 查询用户是否点过赞
        ApComment commentDB;
        try {
             commentDB = findCommentById(commentId);
            if (commentDB == null) {
                CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST, "该评论不存在");
            }

            // TODO ApCommentLike commentLike = mongoTemplate.findOne(query, ApCommentLike.class);
            ApCommentLike commentLike = null;
            if (ApLikesBehavior.Operation.LIKE.getValue() == isLike
                    && commentLike == null) {
                // 2.1 点赞评论，ap_comment_like表中新增一条记录 (前提是用户没有点过赞)
                ApCommentLike apCommentLike = new ApCommentLike();
                apCommentLike.setCommentId(commentId);
                apCommentLike.setAuthorId(loggedUser.getId());
                apCommentLike.setOperation(isLike);
                int newLikes = commentDB.getLikes() + 1;
                commentDB.setLikes(newLikes);

                // 2.2 该评论点赞数超过10，可尝试成为热点评论（热点评论最大为5条）
                if (newLikes > 10 &&
                        commentDB.getFlag().intValue() == ApComment.Flag.NORMAL.getValue()) {
                    commentHotService.hotCommentExecutor(commentDB);
                }
                mongoTemplate.save(apCommentLike);

            } else if (ApLikesBehavior.Operation.UNLIKE.getValue() == isLike
                    && commentLike != null) {
                //  2.2 取消点赞评论，ap_comment_like表中删除一条记录
                // 2.2.1 点赞数最小为0
                int newLikes = commentDB.getLikes() <= 0 ? 0 : commentDB.getLikes() - 1;
                commentDB.setLikes(newLikes);
                // 2.3 删除当前用户对该评论的点赞记录
                mongoTemplate.remove(commentLike);

            } /*else {
                CustException.cust(AppHttpCodeEnum.DATA_NOT_ALLOW, "点赞/取消点赞操作行为不合法");
            }*/

            // 3. 更新评论表中的点赞数
            mongoTemplate.save(commentDB);
        } finally {
            rLock.unlock(); // 释放锁资源
        }
        HashMap<String, Integer> data = new HashMap<>();
        data.put("likes", commentDB.getLikes());
        return ResponseResult.okResult(data);
    }

    @Override
    public ApComment findCommentById(String id) {
        Query query = new Query(Criteria.where("id").is(id));
        ApComment commentDB = mongoTemplate.findOne(query, ApComment.class);
        return commentDB;
    }

    @Override
    public ResponseResult loadComment(CommentDTO dto) {
        // 1. 检查参数
        dto.tryCorrectParams();

        // 2. 查询评论列表
        Criteria criteria = Criteria
                .where("articleId").is(dto.getArticleId())
                .and("createdTime").lt(dto.getMinDate());
        if (dto.getIndex() == 1) { // 查询热点评论
            criteria.and("flag").is(ApComment.Flag.HOT.getValue());
        }
        Query query = new Query(criteria);
        // 2.1 只要前10条
        query.limit(dto.getSize());

        // 2.2  根据发布时间倒序排列
        query.with(Sort.by(Sort.Direction.DESC, "likes"));
        /// query.with(Sort.by(Sort.Direction.DESC, "createdTime"));
        List<ApComment> apComments = mongoTemplate.find(query, ApComment.class);

        List<ApCommentVo> apCommentVos = apComments.stream().map(item -> {
            ApCommentVo apCommentVo = new ApCommentVo();
            BeanUtils.copyProperties(item, apCommentVo);
            if (item.getLikes() > 0) {
                // 2.3 该评论已被点赞
                apCommentVo.setOperation(ApLikesBehavior.Operation.LIKE.getValue());
            } else {
                apCommentVo.setOperation(ApLikesBehavior.Operation.UNLIKE.getValue());
            }
            return apCommentVo;
        }).collect(Collectors.toList());

        // 3. 返回评论结果
        return ResponseResult.okResult(apCommentVos);
    }
}
